from django_redis import get_redis_connection
import json

"""
    Redis 缓存模块
"""


def clear_dict(d):
    """去除对象中的 None"""
    if d is None:
        return None
    elif isinstance(d, list):
        return list(filter(lambda x: x is not None, map(clear_dict, d)))
    elif not isinstance(d, dict):
        return d
    else:
        r = dict(
            filter(
                lambda x: x[1] is not None,
                map(lambda x: (x[0], clear_dict(x[1])), d.items()),
            )
        )
        if not bool(r):
            return None
        return r


def dict_str(dict_hex):
    dict_str = {}
    for k, v in dict_hex.items():
        if type(v) == dict:
            dict_str[k.decode("utf-8")] = dict_str(v)
        else:
            dict_str[k.decode("utf-8")] = v.decode("utf-8")
    return dict_str


def redis_put(table, key, db, t=None):
    rds = get_redis_connection(table)
    if rds.exists(key):
        rds.delete(key)
    for k, v in db.items():
        rds.hset(key, k, v)
    if t:
        rds.expire(key, t)


def redis_get(table, key, field=None):
    rds = get_redis_connection(table)
    if not rds.exists(key):
        return None
    if field:
        return rds.hmget(key, field)[0]  # .decode("utf-8")
    else:
        return dict_str(rds.hgetall(key))


def redis_del(table, key):
    rds = get_redis_connection(table)
    if rds.exists(key):
        rds.delete(key)


def redis_exis(table, key):
    rds = get_redis_connection(table)
    if rds.exists(key):
        return True
    else:
        return False


def redis_putlist(table, key, obj):
    rds = get_redis_connection(table)
    # 将一个或多个值插入到列表头部
    rds.lpush(str(key), str(obj))


def redis_haslist(table, key):
    rds = get_redis_connection(table)
    if rds.llen(str(key)):
        # 移除列表的最后一个元素，返回值为移除的元素。
        return rds.rpop(str(key))
    else:
        return None


# =========str====================================================
def redis_hash_key(tap, key):
    """精准获取key 值"""
    rds = get_redis_connection(tap)
    if not rds.exists(key):
        return None
    return rds.get(key)


def redis_set_key(tap, key, value, t=None):
    """设置字符串值"""
    rds = get_redis_connection(tap)
    rds.set(key, value)
    res = rds.expire(key, t) if t else 0
    return rds.strlen(key)


# =========str====================================================
def redis_key_get(tap, key):
    """精确获取key的值"""
    rds = get_redis_connection(tap)
    if not rds.exists(key):
        return None
    return rds.get(key)


def redis_key_set(tap, key, value, t=None):
    """设置字符串值"""
    rds = get_redis_connection(tap)
    rds.set(key, value)
    res = rds.expire(key, t) if t else 0
    return rds.strlen(key)


# ===========list==================================
def redis_del_list(tap, key, c=0):
    """移除列表左边的数据"""
    rds = get_redis_connection(tap)
    if rds.llen(key):
        return rds.lpop(key)
    else:
        return None


def redis_has_list(tap, key, c=0):
    """获取列表左边的项目"""
    rds = get_redis_connection(tap)
    if rds.llen(key):
        return rds.lindex(key, c)
    else:
        return None


def redis_set_list(tap, key, db):
    """插入数据到右边"""
    rds = get_redis_connection(tap)
    return rds.rpush(key, db)


def redis_list_list(tap, key):
    """获取列表所有元素"""
    rds = get_redis_connection(tap)
    return rds.lrange(key, 0, -1)


# ============hash========================================
def redis_hash_set(tap, key, db, t=0):
    """设置hash"""
    db = clear_dict(db)
    rds = get_redis_connection(tap)
    [rds.hset(key, k, str(v)) for k, v in db.items()]
    res = rds.expire(key, t) if t else 0
    return res


def redis_hash_has(tap, key, field=None):
    """读取hash"""
    rds = get_redis_connection(tap)
    return rds.hget(key, field) if field else rds.hgetall(key)


def redis_hash_list(tap, key):
    """迭代hash"""
    rds = get_redis_connection(tap)
    return rds.hgetall(key)


# =============key==============================================
def redis_key_find(tap, key):
    """模糊查询key"""
    rds = get_redis_connection(tap)
    return rds.keys(key)


def redis_key_scan(tap, cur=0):
    """迭代key"""
    d = []
    rds = get_redis_connection(tap)
    while True:
        r = rds.scan(cur)
        cur = r[0]
        d += r[1]
        if r[0] == 0:
            break
    return d


def redis_key_type(tap, key):
    """返回key类型"""
    rds = get_redis_connection(tap)
    return rds.type(key)


# ===========set==============================================
def redis_sset_list(tap, key):
    """合集中的所有成员"""
    rds = get_redis_connection(tap)
    return rds.smembers(key)


# ===========zset=============================================
def redis_zset_list(tap, key):
    """迭代有序合计"""
    rds = get_redis_connection(tap)
    return rds.zrange(key, 0, -1)


# ============================================================
# String 字符串: key:string
#   set key valur
#   get key
# List 列表: key:list()  不去重
#   lpush key [...]    从左边插入
#   rpush key [...]    从右边插入
# Set 合集：key:list()  自动去重
#   sadd key [...]
#   srem key [...]
# Hash 哈希: key:dict()
#   hset key [field value ...]
#   hget key field
# Zset 有序合集: key:dict()   自动排序
#   zadd key [field value ...]
# ===========================================================


"""
当前存在的KEY:
place       hash    场所基础信息
users       set     用户列表
users__*    hash    用户个人信息
"""


# ==============================================
def Senior_Cache(tap, key, db, s=0):
    """高级存储"""
    rds = get_redis_connection(tap)

    def save_dict(key, db, s=0):
        for k, v in db.items():
            if type(v) == dict:
                save_dict(f"{key}__{k}", v, s)
                rds.hset(key, k, f"{key}__{k}")
                res = rds.expire(key, s) if s else 0
            elif type(v) == list:
                save_list(f"{key}__{k}", v, s)
            else:
                rds.hset(key, k, v)
                res = rds.expire(key, s) if s else 0

    def save_list(key, db, s=0):
        for i in db:
            if type(i) == dict:
                save_dict(f'{key}__{i.get("id")}', i, s)
                rds.sadd(key, f'{key}__{i.get("id")}')
                res = rds.expire(key, s) if s else 0
            elif type(i) == list:
                save_list(f'{key}__{i.get("id")}', i, s)
            else:
                rds.sadd(key, i)
                res = rds.expire(key, s) if s else 0

    # 去除对象中的 None
    db = clear_dict(db)
    ts = type(db)
    if ts == list:
        save_list(key, db, s)
        return rds.scard(key)
    elif ts == dict:
        save_dict(key, db, s)
        return rds.hlen(key)
    else:
        rds.set(key, db)
        res = rds.expire(key, s) if s else 0
        return rds.get(key)
    return None


def Obtain_Cache(tap, key, db=None):
    """高级提取"""
    rds = get_redis_connection(tap)

    def has_dict(key, db=None):
        if db is None:
            res = rds.hgetall(key)
        elif type(db) == list:
            res = rds.hmget(key, db)
        elif type(db) == str:
            res = rds.hget(key, db)
        else:
            res = None
        return res

    def has_list(key, db=None):
        """db 接收迭代查找模式  u*"""
        sess = []
        if db:
            res = rds.sscan(key, 0, db)
            sess += [has_dict(i) if i.find("__") else i for i in res[1]]
        else:
            res = rds.smembers(key)
            sess += [has_dict(i) if i.find("__") else i for i in list(res)]
        return sess

    if not rds.exists(key):
        return None

    s = rds.type(key)
    if s == "set":
        res = has_list(key, db)
    elif s == "hash":
        res = has_dict(key, db)
    else:
        res = None

    return res


# 新接口函数==================================================================================
def new_has_key(tap, key):
    """检测key"""
    rds = get_redis_connection(tap)
    if rds.exists(key):
        return rds.get(key)
    else:
        return None


def new_put_key(tap, key, value, s=0):
    """设置key"""
    rds = get_redis_connection(tap)
    rds.set(key, value)
    res = rds.expire(key, s) if s else 0
